/**
  ******************************************************************************
  * @author     Chris
  * @since      2024/6/24 23:22
  *
  * @file       pd_spi.h
  * @brief      Header file of SPI peripheral driver.
  *
  * @note       This file contains the SPI object declaration.
  *
  * @warning    None.
  ******************************************************************************
  * Change Logs:
  *   Date          Author       Notes
  *   2024/6/24     Chris        the first version
  *
  ******************************************************************************
  */


#ifndef JLC_SKY_SPI_H
#define JLC_SKY_SPI_H

#include "stm32f407xx.h"
#include "pd_gpio.h"

struct SPIVtbl;

// Object properties
typedef struct {
    GPIO *ssel;       // Slave Select
    uint8_t sselSize; // Slave Select line size
    GPIO *sclk;       // Clock
    GPIO *mosi;       // Master Output Slave Input
    GPIO *miso;       // Master Input Slave Output

    struct SPIVtbl *vptr;
} SPI;

// Object virtual table
struct SPIVtbl {
    void (*init)(const SPI *this);

    void (*start)(const SPI *this, const GPIO *ssel);

    uint8_t (*swap_byte)(const SPI *super, uint8_t dat);

    void (*stop)(const SPI *this, const GPIO *ssel);
};

// Object constructor and member function
void SPI_constructor(SPI *this, GPIO *ssel, uint8_t sselSize, GPIO *sclk, GPIO *mosi, GPIO *miso);

static inline void SPI_init(const SPI *this) {
    this->vptr->init(this);
}

static inline void SPI_start(const SPI *this, const GPIO *ssel) {
    this->vptr->start(this, ssel);
}

static inline uint8_t SPI_swapByte(const SPI *this, const uint8_t dat) {
    return this->vptr->swap_byte(this, dat);
}

static inline void SPI_stop(const SPI *this, const GPIO *ssel) {
    this->vptr->stop(this, ssel);
}

#endif //JLC_SKY_SPI_H
